{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div align=\"right\" style=\"text-align: right;\"><i>Peter Norvig<br>Jotto: April 2020<br>Wordle: Jan 2022</i></div>\n",
    "\n",
    "# Jotto and Wordle: Word Guessing Games\n",
    "\n",
    "[Jotto](https://en.wikipedia.org/wiki/Jotto) is a word game in which a **guesser** tries to guess a secret **target** word, which is chosen from a **word list** of allowable words, in as few guesses as possible. Each guess must be one of the allowable words, and the **reply** to each guess is the number of letters in common between the guess word and the target word, regardless of the positions of the letters.   \n",
    "\n",
    "Here is an example Jotto game, where I show the guesses, the replies, the number of remaining consistent target words, and finally the letters that matched (the matches are an aid to you, the reader; they are not known to the guesser). A **consistent target** is a word that would give the same reply to each guess as the replies actually observed.  In this game, the guesser gets to the target word, \"wonky\", in 7 guesses. \n",
    "\n",
    "    Guess 1: \"stoma\" Reply: 1; Consistent targets: 1118    (Matched: \"o\")\n",
    "    Guess 2: \"bairn\" Reply: 1; Consistent targets: 441     (Matched: \"n\")\n",
    "    Guess 3: \"swipe\" Reply: 1; Consistent targets: 197     (Matched: \"w\")\n",
    "    Guess 4: \"lurks\" Reply: 1; Consistent targets: 87      (Matched: \"k\")\n",
    "    Guess 5: \"rowdy\" Reply: 3; Consistent targets: 14      (Matched: \"owy\")\n",
    "    Guess 6: \"roved\" Reply: 1; Consistent targets: 2       (Matched: \"o\")\n",
    "    Guess 7: \"wonky\" Reply: 5; Consistent targets: 1       (Matched: \"wonky\")\n",
    "\n",
    "\n",
    "There are several variants of Jotto; here are five key questions and my answers:\n",
    "\n",
    "- How many letters can each word have? <br>**Five**.\n",
    "- Does a guess have to be a word in the word list? <br>**Yes.**\n",
    "- Can a word have repeated letters, like the \"s\" in \"stars\"? <br>**No.** Every word must have 5 different letters.\n",
    "- What if the reply is \"5\", but the guess is not the target?<br>**Not allowed**. No two words in the word list may have the same set of five letters.<br>(For example, only one of the anagrams apers/pares/parse/pears/reaps/spare/spear is allowed.)\n",
    "- Who chooses the target word? <br>**Random chance**. Jotto is sometimes a two-person game where the chooser is an adversary, but not here.\n",
    "\n",
    "# Jotto Preliminaries\n",
    "\n",
    "First off, some Python basics: Import some modules and define the basic types `Word`, `Score`, and `Reply`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing      import List, Tuple, Dict, Union, Counter, Callable, Iterable\n",
    "from dataclasses import dataclass\n",
    "from statistics  import mean, median, stdev\n",
    "from collections import defaultdict\n",
    "from math        import log2\n",
    "import random \n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "Word  = str # A word is a lower-case string of five different letters\n",
    "Score = int # A score is the number of guesses it took to get the target word\n",
    "Reply = int # A reply is the number of letters in common between guess and target words\n",
    "\n",
    "random.seed(42) # For reproducibility"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can make a Jotto word list by:\n",
    "- Starting with a file containing a list of words.\n",
    "- Discarding the ones that don't have 5 distinct letters.\n",
    "- Putting the rest into a dict of anagrams keyed by the set of letters.\n",
    "- Keeping only one word for each anagram."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_words(filename) -> List[Word]: return open(filename).read().split()\n",
    "\n",
    "def allowable(words) -> List[Word]:\n",
    "    \"\"\"Build a list of allowable Jotto words from an iterable of words.\"\"\"\n",
    "    anagrams = {frozenset(w): w for w in words if len(w) == 5 == len(set(w))}\n",
    "    return list(anagrams.values())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The [Stanford GraphBase project](https://www-cs-faculty.stanford.edu/~knuth/sgb.html) has a nice list of five-letter words, [sgb-words.txt](sgb-words.txt):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2845"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "! [ -e sgb-words.txt ] || curl -O https://norvig.com/ngrams/sgb-words.txt\n",
    "    \n",
    "wordlist = allowable(read_words('sgb-words.txt'))\n",
    "\n",
    "len(wordlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We see there are 2,845 allowable Jotto words in [sgb-words.txt](sgb-words.txt)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Playing Jotto\n",
    "\n",
    "The function `play` will play a game of Jotto and return the score (the number of guesses). The  arguments are:\n",
    "- `guesser`: a `callable` (e.g., a function) that should return the guess to make. The guesser is passed two arguments: \n",
    "  - The reply to the previous guess.\n",
    "  - A list of the words that are consistent with all the guesses made so far. \n",
    "<br>(If the guesser wants to keep track of all the guesses made so far, or all the words in the word list, it can.)\n",
    "- `target`: The target word. If none is given, the target word is chosen at random from the wordlist.\n",
    "- `wordlist`: The list of allowable words.\n",
    "- `verbose`: Unless false, print a message for each guess.\n",
    "\n",
    "Two corner cases: \n",
    "1. If the guesser improperly guesses a non-word, the reply is `None`. \n",
    "2. To prevent an infinite loop, the worst score you can get is the number of words in the wordlist."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "Guesser = Callable[[Reply, List[Word]], Word]\n",
    "\n",
    "def play(guesser: Guesser, target=None, wordlist=wordlist, verbose=True) -> Score:\n",
    "    \"\"\"The number of guesses it take for `guesser` to guess the Jotto word,\n",
    "    which is given by `target` or selected from the words in `wordlist`?\"\"\"\n",
    "    target  = target or random.choice(wordlist) # Choose a random target if none was given\n",
    "    targets = wordlist      # The targets that are consistent with all replies\n",
    "    reply   = None          # For the first guess, there is no previous reply\n",
    "    N       = len(wordlist)\n",
    "    for turn in range(1, N + 1):\n",
    "        guess = guesser(reply, targets)\n",
    "        reply = reply_for(guess, target) if guess in wordlist else None\n",
    "        targets = [t for t in targets if reply_for(guess, t) == reply]\n",
    "        if verbose: \n",
    "            print(f'Guess {turn}: \"{guess}\" Reply: {reply}; Consistent targets: {len(targets)}')\n",
    "        if guess == target or turn == N:  \n",
    "            return turn\n",
    "                         \n",
    "def reply_for(guess, target) -> Reply: \n",
    "    \"The number of letters in common between the target and guess\"\n",
    "    return len(set(target).intersection(guess))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To play a game, we will need a guesser. Here are two simple ones:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def human_guesser(reply, targets) -> Word: \n",
    "    \"\"\"Ask a human to make a guess.\"\"\"\n",
    "    return input(f'Reply was {reply}. Your guess? ')\n",
    "\n",
    "def random_guesser(reply, targets) -> Word: \n",
    "    \"\"\"Choose a guess at random from the consistent targets.\"\"\"\n",
    "    return random.choice(targets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sample Jotto Games\n",
    "\n",
    "Here is the `random_guesser` in action:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"strop\" Reply: 3; Consistent targets: 322\n",
      "Guess 2: \"party\" Reply: 1; Consistent targets: 112\n",
      "Guess 3: \"obits\" Reply: 3; Consistent targets: 44\n",
      "Guess 4: \"sloth\" Reply: 2; Consistent targets: 12\n",
      "Guess 5: \"brows\" Reply: 2; Consistent targets: 5\n",
      "Guess 6: \"pious\" Reply: 4; Consistent targets: 4\n",
      "Guess 7: \"pions\" Reply: 4; Consistent targets: 3\n",
      "Guess 8: \"dipso\" Reply: 5; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(random_guesser)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"carpy\" Reply: 0; Consistent targets: 602\n",
      "Guess 2: \"litho\" Reply: 2; Consistent targets: 249\n",
      "Guess 3: \"loved\" Reply: 0; Consistent targets: 21\n",
      "Guess 4: \"fugit\" Reply: 2; Consistent targets: 7\n",
      "Guess 5: \"skint\" Reply: 1; Consistent targets: 1\n",
      "Guess 6: \"thumb\" Reply: 5; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(random_guesser)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"thous\" Reply: 1; Consistent targets: 1141\n",
      "Guess 2: \"vocal\" Reply: 2; Consistent targets: 340\n",
      "Guess 3: \"snack\" Reply: 0; Consistent targets: 46\n",
      "Guess 4: \"vigor\" Reply: 2; Consistent targets: 19\n",
      "Guess 5: \"oxlip\" Reply: 2; Consistent targets: 10\n",
      "Guess 6: \"roble\" Reply: 3; Consistent targets: 4\n",
      "Guess 7: \"world\" Reply: 5; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(random_guesser, target='world')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  Partitioning Target Words\n",
    "\n",
    "A key idea in guessing is to reduce the number of consistent targets. When there is a single consistent target left, the game is over. We can think of a guess as **partitioning** the consistent targets into different **branches** of a tree, each branch corresponding to a different reply:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def partition(guess, targets) ->  Dict[Reply, List[str]]:\n",
    "    \"\"\"A guess partition targets by the possible replies to guess: {reply: [word, ...]}.\"\"\"\n",
    "    branches = defaultdict(list)\n",
    "    for target in targets:\n",
    "        branches[reply_for(guess, target)].append(target)\n",
    "    return branches"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To get a feel for how this works, a 2,845 word list is too much to deal with; let's consider just the first 22 words in `wordlist`. Here are two partitions of those 22 words, one by the guess `'girth'` and one by `'ethos'`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "words22 = wordlist[:22]\n",
    "\n",
    "assert (partition('girth', words22) ==\n",
    "       {0: ['would', 'cloud', 'place', 'sound', 'fondu'],\n",
    "        1: ['about', 'sword', 'resay', 'nuder', 'house'],\n",
    "        2: ['water', 'after', 'ethos', 'while'],\n",
    "        3: ['throe', 'write', 'rifts', 'think', 'grate'],\n",
    "        4: ['their', 'might'],\n",
    "        5: ['girth']})\n",
    "\n",
    "assert (partition('ethos', words22) ==\n",
    "       {1: ['would', 'cloud', 'place', 'fondu', 'nuder'],\n",
    "        2: ['about', 'sword', 'write', 'rifts', 'water', 'after', 'girth', 'think', 'resay', \n",
    "            'sound', 'grate', 'might', 'while'],\n",
    "        3: ['their'],\n",
    "        4: ['throe', 'house'],\n",
    "        5: ['ethos']})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "No matter what the reply to `'girth'` is,  we will be left with no more than 5 targets. \n",
    "\n",
    "But if we guess `'ethos'` then 13 of the 22 targets would get a reply of 2, and there would be 13 possible targets remaining to deal with. That  suggests that `'girth'` is a better guess and that a good strategy is: **guess a word that partitions the possible targets into small branches.**\n",
    "\n",
    "Since we only need to know the *size* of each branch, not the list of words therein, we can use `partition_counts`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def partition_counts(guess, targets) -> List[int]: \n",
    "    \"The sizes of the branches of a partition of targets by guess.\"\n",
    "    counter = Counter(reply_for(guess, target) for target in targets)\n",
    "    return list(counter.values())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 5, 5, 5, 4, 1]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "partition_counts('girth', words22)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 13, 5, 2, 1]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "partition_counts('ethos', words22)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Metrics for Minimizing Partitions\n",
    "\n",
    "We want partitions with **small branches**, but what exactly does that mean? Ideally, we want the partition that minimizes the average number of additional guesses it will take to finish the game. But since we don't know that, we can instead minimize one of the following proxy metrics:\n",
    "\n",
    "- **Maximum**: choose the partition that minimizes the size of the largest branch.\n",
    "\n",
    "- **Expectation**: In probability theory, the expectation (also known as expected value) is the weighted average of a random variable. Here it means the sum, over all branches, of the probability of ending up in the branch multiplied by the size of the branch. We are assuming that every target is equally likely, so the probability of a branch is proportional to the number of targets in it.\n",
    "\n",
    "- **Negative Entropy**: In information theory, entropy is the weighted average amount of \"information\" measured in bits. The calculation is the same as expectation except that we count the base 2 logarithm of the branch sizes, not the branches sizes themselves. You can think of the base 2 logarithm as the number of times that you need to cut a branch in half to get it down to one word. We want to maximize entropy, or minimize *negative* entropy.\n",
    "\n",
    "The maximum is just the builtin `max` function; here are the other two metrics:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def expectation(counts: List[int]) -> float:\n",
    "    \"The expected value of the counts.\"\n",
    "    N = sum(counts)\n",
    "    def P(x): return x / N\n",
    "    return sum(P(x) * x for x in counts)\n",
    "\n",
    "def neg_entropy(counts: List[int]) -> float: \n",
    "    \"\"\"The negation of the entropy of the counts.\"\"\"\n",
    "    N = sum(counts)\n",
    "    def P(x): return x / N\n",
    "    return sum(P(x) * log2(P(x)) for x in counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  Caching Best Guesses: Guess Trees\n",
    "\n",
    "Going through every word in the wordlist to decide which one makes the best partition takes some time. I would prefer to do that computation just once and cache it, rather than have to repeat the computation in every new game. I will cache the best guesses in a structure called a **guess tree**: a tree that has branches for every possible path the game might take, with the best guess for each situation already computed. A guess tree is either:\n",
    "- An **interior node**, which has a guess and a dict of branches, `Node(guess, {reply: subtree, ...})`, where  each subtree covers all the target words that are consistent with the corresponding reply.\n",
    "- A **leaf word**,  indicating the sole remaining consistent target word. Every word in the word list should appear as a leaf in exactly one place in a guess tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "@dataclass \n",
    "class Node:\n",
    "    \"\"\"A node in a guess tree. It stores the best guess, and a branch for every possible reply.\"\"\"\n",
    "    guess: Word\n",
    "    branches: Dict[Reply, 'Tree']\n",
    "        \n",
    "    def __repr__(self) -> str: return f'Node(\"{self.guess}\", {self.branches})'\n",
    "\n",
    "Tree = Union[Node, Word] # A Tree is either an interior Node or a leaf Word"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The function `minimizing_tree(metric, targets)` builds a guess tree that covers all the targets and that, at every node, guesses a word that  minimizes the `metric` applied to the `partition_counts` of the guess."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def minimizing_tree(metric, targets) -> Tree:\n",
    "    \"\"\"Make a tree that picks guesses that minimize metric(partition_counts(guess, targets)).\"\"\"\n",
    "    if len(targets) == 1:\n",
    "        return targets[0]\n",
    "    else:\n",
    "        guess = min(targets, key=lambda guess: metric(partition_counts(guess, targets))) \n",
    "        branches = partition(guess, targets)\n",
    "        return Node(guess, {reply: minimizing_tree(metric, branches[reply]) \n",
    "                            for reply in branches})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is a minimizing tree that covers the 22 words. The tree says that the first guess is `\"girth\"`, and if the reply is `0` the next guess is `\"would\"`. If, say, the reply to `\"would\"` is 4, then there is only one other word left, the leaf word `'cloud'`. If the reply is 5, that means `\"would\"` was correct. I won't go through the other branches of the tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "tree22 = minimizing_tree(max, words22)\n",
    "\n",
    "assert (tree22 ==\n",
    "        Node(\"girth\", \n",
    "             {0: Node(\"would\", \n",
    "                      {1: 'place', \n",
    "                       3: Node(\"sound\", {4: 'fondu', 5: 'sound'}), \n",
    "                       4: 'cloud', \n",
    "                       5: 'would'}), \n",
    "              1: Node(\"about\", \n",
    "                      {1: Node(\"sword\", \n",
    "                               {2: Node(\"resay\", {2: 'nuder', 5: 'resay'}), \n",
    "                                5: 'sword'}), \n",
    "                       2: 'house', \n",
    "                       5: 'about'}), \n",
    "              2: Node(\"after\", \n",
    "                      {1: 'while', \n",
    "                       2: 'ethos', \n",
    "                       4: 'water', \n",
    "                       5: 'after'}), \n",
    "              3: Node(\"throe\", \n",
    "                      {2: Node(\"rifts\", {2: 'think', 5: 'rifts'}), \n",
    "                       3: Node(\"write\", {3: 'grate', 5: 'write'}), \n",
    "                       5: 'throe'}), \n",
    "              4: Node(\"their\", \n",
    "                      {3: 'might', \n",
    "                       5: 'their'}), \n",
    "              5: 'girth'}))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Turning a Tree into a Guesser\n",
    "\n",
    "A tree is not a guesser, but we can easily make a guesser from a tree. A `TreeGuesser` works as follows:\n",
    "- When *initialized*, it takes a tree as input, and stores the tree under the `.root` attribute.\n",
    "- When *called*, it sets the `.tree` attribute:\n",
    "  - For the first turn in a game (when the reply is `None`), it resets `.tree`  to `.root`.\n",
    "  - On subsequent turns, it updates `.tree` to be the branch corresponding to the reply.\n",
    "- It then returns the guess for the current tree: either the `.guess` attribute  or the leaf word. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "class TreeGuesser:\n",
    "    \"\"\"Given a guess tree, use it to create a callable Guesser that can play Jotto.\"\"\"\n",
    "    def __init__(self, tree): self.root = tree\n",
    "        \n",
    "    def __call__(self, reply, targets) -> Word:\n",
    "        \"\"\"If reply is None, start a new game; otherwise follow the branch for the reply.\n",
    "        Then return the current leaf or interior node guess.\"\"\"\n",
    "        tree = self.tree = self.root if reply is None else self.tree.branches[reply]\n",
    "        return tree.guess if isinstance(tree, Node) else tree"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we build a tree that minimizes the maximum branch size (over the full wordlist) and make a guesser out of it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "tree = minimizing_tree(max, wordlist)\n",
    "guesser = TreeGuesser(tree)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sample Games with the Minimizing Guesser\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"wader\" Reply: 0; Consistent targets: 466\n",
      "Guess 2: \"tings\" Reply: 2; Consistent targets: 160\n",
      "Guess 3: \"gunky\" Reply: 1; Consistent targets: 54\n",
      "Guess 4: \"bouts\" Reply: 2; Consistent targets: 16\n",
      "Guess 5: \"clogs\" Reply: 0; Consistent targets: 1\n",
      "Guess 6: \"mufti\" Reply: 5; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(guesser)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"wader\" Reply: 1; Consistent targets: 1012\n",
      "Guess 2: \"actin\" Reply: 2; Consistent targets: 355\n",
      "Guess 3: \"flats\" Reply: 2; Consistent targets: 113\n",
      "Guess 4: \"cloak\" Reply: 3; Consistent targets: 17\n",
      "Guess 5: \"backs\" Reply: 2; Consistent targets: 5\n",
      "Guess 6: \"clamp\" Reply: 3; Consistent targets: 2\n",
      "Guess 7: \"plank\" Reply: 5; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(guesser)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"wader\" Reply: 3; Consistent targets: 319\n",
      "Guess 2: \"sword\" Reply: 1; Consistent targets: 131\n",
      "Guess 3: \"paled\" Reply: 4; Consistent targets: 21\n",
      "Guess 4: \"abled\" Reply: 3; Consistent targets: 8\n",
      "Guess 5: \"paved\" Reply: 4; Consistent targets: 6\n",
      "Guess 6: \"caped\" Reply: 4; Consistent targets: 5\n",
      "Guess 7: \"paged\" Reply: 4; Consistent targets: 4\n",
      "Guess 8: \"adept\" Reply: 4; Consistent targets: 3\n",
      "Guess 9: \"paned\" Reply: 4; Consistent targets: 2\n",
      "Guess 10: \"payed\" Reply: 4; Consistent targets: 1\n",
      "Guess 11: \"amped\" Reply: 5; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "11"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(guesser)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making Inconsistent Guesses\n",
    "\n",
    "So far,  we have always guessed one of the consistent targets. That seems reasonable; why waste a guess on a word that could not possibly be the target? But it turns out that in some cases it ***is*** a good strategy to guess such a word.\n",
    "\n",
    "Consider the branch of `tree22` where the reply to the first guess is 1. There are 5 consistent words remaining, and the max-minimizing tree (which starts by guessing `\"about\"`), can take up to 4 more guesses to find the target:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert (tree22.branches[1] == \n",
    "        Node(\"about\", \n",
    "             {1: Node(\"sword\", \n",
    "                      {2: Node(\"resay\", \n",
    "                               {2: 'nuder', \n",
    "                                5: 'resay'}), \n",
    "                       5: 'sword'}), \n",
    "              2: 'house', \n",
    "              5: 'about'}))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But now consider this tree, which covers the same five words:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "tree5 = Node(\"nerdy\", {0: 'about', \n",
    "                       1: 'house', \n",
    "                       2: 'sword', \n",
    "                       3: 'resay', \n",
    "                       4: 'nuder'})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The first guess, `\"nerdy\"` is inconsistent–it is not one of the five words. This tree sacrifices the 1-in-5 chance of being right on the first guess in order to be assured that the second guess will be correct. So the min, max, mean, and median is 2 guesses. On the whole, this is better than guessing `\"about\"`, which gives a mean of 2.4 and a worst case of 4.  \n",
    "\n",
    "I will redefine `minimizing_tree` so that it is passed both the list of remaining consistent target words and the complete word list. It also takes a flag, `inconsistent`. When this flag is true, any word in the wordlist can be considered as a guess; when false, only consistent targets are considered, as before. (Note: when there are 3 or fewer target words left there is no use considering inconsistent guesses, since they cannot improve the average score over a consistent guess. Also, when there are many targets, the odds are one of them will be as good as any inconsistent guess. The value of *many* was empirically chosen as `inconsistent_max = 400`.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "def minimizing_tree(metric, targets, wordlist=wordlist, inconsistent=False) -> Tree:\n",
    "    \"\"\"Make a tree that picks guesses that minimize metric(partition_counts(guess, targets)).\"\"\"\n",
    "    if len(targets) == 1:\n",
    "        return targets[0]\n",
    "    else:\n",
    "        guesses  = wordlist if (inconsistent and 3 < len(targets) <= inconsistent_max) else targets\n",
    "        guess    = min(guesses, key=lambda guess: metric(partition_counts(guess, targets))) \n",
    "        branches = partition(guess, targets)\n",
    "        return Node(guess, {reply: minimizing_tree(metric, branches[reply], wordlist, inconsistent) \n",
    "                            for reply in sorted(branches)})\n",
    "    \n",
    "inconsistent_max = 400"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "words5 = ['about', 'house', 'sword', 'resay', 'nuder']\n",
    "\n",
    "assert minimizing_tree(max, words5, inconsistent=True) == tree5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Evaluating and Reporting on Guessers\n",
    "\n",
    "To properly evaluate a guesser, a sample of 3 games is not enough to be statistically reliable. I'll introduce three functions that together will evaluate a guesser and produce a report:\n",
    "\n",
    "- `report_minimizing_tree` builds a minimizing tree, gets its tree scores, and calls `report`.\n",
    "- `report` takes a list of scores and reports the following statistics:\n",
    "  - The median, mean, standard deviation, and worst case number of guesses, and total number of scores.\n",
    "  - The cumulative percentages guessed correctly (e.g., `\"≤5:11%\"` means 11% of the targets took 5 or fewer guesses).\n",
    "  - A histogram of scores.\n",
    "- `tree_scores` takes a guesser and returns a list of *all* the scores it would make for *all* its targets. For each subtree branch in the tree there are three cases:\n",
    "  - If the subtree is a leaf word that is the same as the node's guess, we're done; it took one guess.\n",
    "  - If the subtree is a leaf word that is not the guess, it took two guesses: one for the incorrect guess and one for the leaf word.\n",
    "  - If the subtree is a Node, add one to each of the scores from the subtree and yield those scores."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "def report_minimizing_tree(metric, targets=wordlist, wordlist=wordlist, inconsistent=False) -> Tree:\n",
    "    \"\"\"Build a minimizing tree and report on its scores.\"\"\"\n",
    "    print(f\"minimizing the {metric.__name__} of partition sizes over\",\n",
    "          f\"{len(targets):,d} targets in a {len(wordlist):,d} word list,\")\n",
    "    print(f\"{'' if inconsistent else 'not '}including inconsistent words.\")\n",
    "    tree = minimizing_tree(metric, targets, wordlist, inconsistent)\n",
    "    print(f'first guess: \"{tree.guess}\"')\n",
    "    report(tree_scores(tree))\n",
    "    return tree\n",
    "\n",
    "def report(scores: Iterable[Score], label='') -> None:\n",
    "    \"\"\"Report statistics and a histogram for these scores.\"\"\"\n",
    "    scores  = list(scores)\n",
    "    ctr     = Counter(scores)\n",
    "    bins    = range(min(ctr), max(ctr) + 2)\n",
    "    scale   = 100 / len(scores)\n",
    "    weights = [scale * ctr[score] for score in ctr]\n",
    "    plt.hist(list(ctr), weights=weights, align='left', rwidth=0.9, bins=bins)\n",
    "    plt.xticks(bins[:-1])\n",
    "    plt.xlabel('Number of guesses'); plt.ylabel('% of scores')\n",
    "    def cumulative_pct(g) -> str: \n",
    "        \"\"\"What percent of games requires no more than g guesses?\"\"\"\n",
    "        percent = scale * sum(ctr[i] for i in range(1, g + 1))\n",
    "        return f'≤{g}:{percent:.{1 if 99 < percent < 100 else 0}f}%'\n",
    "    print(f'median: {median(scores):.0f} guesses, mean: {mean(scores):.2f}',\n",
    "          f'± {stdev(scores):.2f}, worst: {max(scores)}, scores: {len(scores):,d}\\n'\n",
    "          'cumulative:', ', '.join(map(cumulative_pct, range(3, 11))))\n",
    "    \n",
    "def tree_scores(node: Node) -> Iterable[Score]:\n",
    "    \"\"\"All the scores for playing all the target words in the tree under `node`.\"\"\"\n",
    "    for subtree in node.branches.values():\n",
    "        if isinstance(subtree, Word):\n",
    "            yield 1 if subtree == node.guess else 2\n",
    "        else:\n",
    "            yield from (score + 1 for score in tree_scores(subtree))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To test these functions, and to give another example of inconsistent guessing, consider this list of 11 words:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "ails = 'bails fails hails jails mails nails pails rails tails vails wails'.split()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A consistent guesser could guess them in any order, but wouldn't gain much information from the replies–every reply is either a 5 (which ends the game) or a 4, which leaves you with all the remaining words.   Here is the report:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the max of partition sizes over 11 targets in a 2,845 word list,\n",
      "not including inconsistent words.\n",
      "first guess: \"bails\"\n",
      "median: 6 guesses, mean: 6.00 ± 3.32, worst: 11, scores: 11\n",
      "cumulative: ≤3:27%, ≤4:36%, ≤5:45%, ≤6:55%, ≤7:64%, ≤8:73%, ≤9:82%, ≤10:91%\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "t = report_minimizing_tree(max, ails)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But an inconsistent guesser can make a guesses that more evenly partition the remaining words, giving an average of only 4 guesses, and a worst case of 5 guesses: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the max of partition sizes over 11 targets in a 2,845 word list,\n",
      "including inconsistent words.\n",
      "first guess: \"front\"\n",
      "median: 4 guesses, mean: 4.00 ± 0.77, worst: 5, scores: 11\n",
      "cumulative: ≤3:27%, ≤4:73%, ≤5:100%, ≤6:100%, ≤7:100%, ≤8:100%, ≤9:100%, ≤10:100%\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "t = report_minimizing_tree(max, ails, inconsistent=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Reports on Consistent  Guessers\n",
    "\n",
    "Here are reports on trees made from minimizing the three metrics, with only consistent guesses allowed: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the max of partition sizes over 2,845 targets in a 2,845 word list,\n",
      "not including inconsistent words.\n",
      "first guess: \"wader\"\n",
      "median: 7 guesses, mean: 7.15 ± 1.81, worst: 18, scores: 2,845\n",
      "cumulative: ≤3:1%, ≤4:4%, ≤5:13%, ≤6:35%, ≤7:67%, ≤8:86%, ≤9:92%, ≤10:95%\n",
      "CPU times: user 6.73 s, sys: 11.3 ms, total: 6.74 s\n",
      "Wall time: 6.75 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(max, inconsistent=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the expectation of partition sizes over 2,845 targets in a 2,845 word list,\n",
      "not including inconsistent words.\n",
      "first guess: \"raved\"\n",
      "median: 7 guesses, mean: 7.14 ± 1.82, worst: 17, scores: 2,845\n",
      "cumulative: ≤3:1%, ≤4:4%, ≤5:13%, ≤6:36%, ≤7:68%, ≤8:85%, ≤9:91%, ≤10:95%\n",
      "CPU times: user 6.43 s, sys: 5.51 ms, total: 6.44 s\n",
      "Wall time: 6.44 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(expectation, inconsistent=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the neg_entropy of partition sizes over 2,845 targets in a 2,845 word list,\n",
      "not including inconsistent words.\n",
      "first guess: \"debar\"\n",
      "median: 7 guesses, mean: 7.09 ± 1.78, worst: 19, scores: 2,845\n",
      "cumulative: ≤3:1%, ≤4:4%, ≤5:13%, ≤6:36%, ≤7:69%, ≤8:86%, ≤9:92%, ≤10:96%\n",
      "CPU times: user 6.45 s, sys: 6.68 ms, total: 6.46 s\n",
      "Wall time: 6.46 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(neg_entropy, inconsistent=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The random guesser can also be classified as a consistent guesser. Here is a report on it:|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "median: 7 guesses, mean: 7.42 ± 1.71, worst: 17, scores: 2,845\n",
      "cumulative: ≤3:1%, ≤4:3%, ≤5:11%, ≤6:28%, ≤7:55%, ≤8:77%, ≤9:91%, ≤10:96%\n",
      "CPU times: user 6.57 s, sys: 9.57 ms, total: 6.58 s\n",
      "Wall time: 6.58 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time report(play(random_guesser, target, wordlist, verbose=False) for target in wordlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The random consistent guesser strategy might have seemed hopelessly naive, but it is actually a pretty decent strategy, with mean number of guesses only 5% worse than the best minimizing tree. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Reports on Inconsistent  Guessers\n",
    "Now we'll report on trees with inconsistent guesses allowed. This will take longer; about 30 seconds per tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the max of partition sizes over 2,845 targets in a 2,845 word list,\n",
      "including inconsistent words.\n",
      "first guess: \"wader\"\n",
      "median: 7 guesses, mean: 7.05 ± 0.98, worst: 10, scores: 2,845\n",
      "cumulative: ≤3:0%, ≤4:1%, ≤5:6%, ≤6:24%, ≤7:69%, ≤8:95%, ≤9:99.9%, ≤10:100%\n",
      "CPU times: user 25.9 s, sys: 17.6 ms, total: 25.9 s\n",
      "Wall time: 25.9 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(max, inconsistent=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the expectation of partition sizes over 2,845 targets in a 2,845 word list,\n",
      "including inconsistent words.\n",
      "first guess: \"raved\"\n",
      "median: 7 guesses, mean: 6.84 ± 0.95, worst: 10, scores: 2,845\n",
      "cumulative: ≤3:0%, ≤4:1%, ≤5:7%, ≤6:32%, ≤7:78%, ≤8:97%, ≤9:100.0%, ≤10:100%\n",
      "CPU times: user 26.3 s, sys: 19.1 ms, total: 26.3 s\n",
      "Wall time: 26.3 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(expectation, inconsistent=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the neg_entropy of partition sizes over 2,845 targets in a 2,845 word list,\n",
      "including inconsistent words.\n",
      "first guess: \"debar\"\n",
      "median: 7 guesses, mean: 6.82 ± 1.00, worst: 10, scores: 2,845\n",
      "cumulative: ≤3:0%, ≤4:1%, ≤5:8%, ≤6:35%, ≤7:78%, ≤8:97%, ≤9:99.6%, ≤10:100%\n",
      "CPU times: user 27.1 s, sys: 24.7 ms, total: 27.2 s\n",
      "Wall time: 27.2 s\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAEGCAYAAABiq/5QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAXLElEQVR4nO3de7SddX3n8ffHEORqo3JgIiENpYhOmRL0GLE4FgEZBIaLl1WYgrTSCVZBqNYamYva1jWgVSxOS1ckQmaJUORSEBgww6UOHRtIIEAwUBSjEwnkIKACioR85o/nd8bDybnsXJ5nJ/l9Xmvttffz7Mv3uzV89nN++9m/n2wTERH1eFm/G4iIiG4l+CMiKpPgj4ioTII/IqIyCf6IiMps1+8GerHbbrt51qxZ/W4jImKrsnTp0idsD4zev1UE/6xZs1iyZEm/24iI2KpI+sFY+zPUExFRmQR/RERlEvwREZVJ8EdEVCbBHxFRmQR/RERlEvwREZVJ8EdEVCbBHxFRma3il7sRMb5Z827orNbKc4/urFa0J0f8ERGVSfBHRFQmwR8RUZkEf0REZRL8ERGVSfBHRFQmwR8RUZkEf0REZRL8ERGVaT34JU2RdI+k68v23pIWS3pY0t9L2r7tHiIi4le6OOI/C1gxYvs84Hzb+wJPAad10ENERBStBr+kGcDRwEVlW8ChwJXlIQuB49vsISIiXqrtI/4vAn8GrCvbrwaetr22bK8C9hzriZLmSloiacnQ0FDLbUZE1KO14Jd0DLDG9tKRu8d4qMd6vu35tgdtDw4MDLTSY0REjdqclvlg4FhJRwE7AK+g+QtgmqTtylH/DODRFnuIiIhRWjvit/0J2zNszwJOBG61/fvAbcB7ysNOBa5tq4eIiFhfP87j/zjwEUnfpRnzX9CHHiIiqtXJCly2bwduL7cfAeZ0UTciItaXX+5GRFQmwR8RUZkEf0REZRL8ERGVSfBHRFQmwR8RUZkEf0REZRL8ERGVSfBHRFQmwR8RUZkEf0REZRL8ERGVSfBHRFQmwR8RUZkEf0REZdpcc3cHSXdKulfSA5I+XfZfIun7kpaVy+y2eoiIiPW1uRDL88Chtp+RNBW4Q9L/LPd9zPaVLdaOiIhxtBb8tg08UzanlovbqhcREb1pdYxf0hRJy4A1wCLbi8tdn5F0n6TzJb18nOfOlbRE0pKhoaE224yIqEqrwW/7RduzgRnAHEn7A58AXge8CXgVzeLrYz13vu1B24MDAwNtthkRUZVOzuqx/TTNYutH2l7txvPAxWTh9YiITrV5Vs+ApGnl9o7A4cCDkqaXfQKOB5a31UNERKyvzbN6pgMLJU2h+YC5wvb1km6VNAAIWAZ8oMUeIiJilDbP6rkPOHCM/Ye2VTMiIiaXX+5GRFQmwR8RUZkEf0REZRL8ERGVSfBHRFQmwR8RUZkEf0REZRL8ERGVSfBHRFQmwR8RUZkEf0REZRL8ERGVSfBHRFQmwR8RUZkEf0REZdpcgWsHSXdKulfSA5I+XfbvLWmxpIcl/b2k7dvqISIi1tfmEf/zwKG2DwBmA0dKOgg4Dzjf9r7AU8BpLfYQERGjtBb8ZUH1Z8rm1HIxcChwZdm/kGbd3YiI6EirY/ySpkhaBqwBFgHfA562vbY8ZBWw5zjPnStpiaQlQ0NDbbYZEVGVVoPf9ou2ZwMzgDnA68d62DjPnW970PbgwMBAm21GRFSlk7N6bD8N3A4cBEyTNLzI+wzg0S56iIiIRptn9QxImlZu7wgcDqwAbgPeUx52KnBtWz1ERMT6tpv8IRttOrBQ0hSaD5grbF8v6TvA5ZL+ErgHWNBiDxERMUprwW/7PuDAMfY/QjPeHxERfZBf7kZEVCbBHxFRmQR/RERlEvwREZVJ8EdEVGbS4Jf0WUmvkDRV0i2SnpB0chfNRUTE5tfLEf8Rtn8KHEMzt85rgY+12lVERLSml+CfWq6PAi6z/WSL/URERMt6+QHXNyQ9CPwc+KCkAeAX7bYVERFtmfSI3/Y84C3AoO0XgOeA49puLCIi2tHLl7s7AR8CLiy7XgMMttlURES0p5ehnouBpcDvlO1VwNeB69tqKmJrM2veDZ3WW3nu0Z3Wi21LL1/u7mP7s8ALALZ/DqjVriIiojW9BP8vy3z6BpC0D81C6hERsRXqZajnk8BNwF6SLgUOBv6gzaYiIqI9Ewa/JAEPAu+iWTZRwFm2n+igt4iIaMGEQz22DfyD7R/bvsH29b2GvqS9JN0maYWkBySdVfZ/StKPJC0rl6M2w/uIiIge9TLU88+S3mT7rg187bXAR23fLWlXYKmkReW+823/1Qa+XkREbAa9BP/bgdMl/QB4lma4x7Z/e6In2V4NrC63fyZpBbDnJvYbERGbqJfgf+emFpE0i2b93cU0Xw6fIel9wBKavwqeGuM5c4G5ADNnztzUFiIiouhlyoYfANOAf18u08q+nkjaBbgKOLvM8nkhsA8wm+Yvgs+PU3e+7UHbgwMDA72Wi4iISfQyZcNZwKXA7uXyVUln9vLikqbShP6ltq8GsP247RdtrwO+DMzZ2OYjImLD9TLUcxrwZtvPAkg6D/g28KWJnlROBV0ArLD9hRH7p5fxf4ATgOUb03hERGycXoJfwIsjtl+ktykbDgZOAe6XtKzsOwc4SdJsml8CrwRO77nbiIjYZL1O0rZY0jVl+3iaI/kJ2b6DsT8gbuy9vYiI2NwmDX7bX5B0O/BWmiD/Q9v3tN1YRES0Y9Lgl3QQ8IDtu8v2rpLebHtx691FRMRm18vsnBcCz4zYfpZfLcoSERFbmV6CX2XOHgDKaZi9fDcQERFboF6C/xFJH5Y0tVzOAh5pu7GIiGhHL8H/AZplF39Es+zimylTKURExNanl7N61gAndtBLRER0oJcpGz4r6RVlmOcWSU9IOrmL5iIiYvPrZajniDK52jE0Qz2vBT7WalcREdGaXoJ/ark+CrjM9pMt9hMRES3r5bTMb0h6EPg58EFJA8Av2m0rIiLa0st8/POAtwCDtl8AngOOa7uxiIhoR08/xBq5QlaZnvnZ1jqKiIhW9TLGHxER25Bxg1/SweX65d21ExERbZvoiP+Ccv3tjXlhSXtJuk3SCkkPlKkekPQqSYskPVyuX7kxrx8RERtnojH+FyRdDOwp6YLRd9r+8CSvvRb4qO27Je0KLJW0CPgD4Bbb50qaB8wDPr5x7UdExIaaKPiPAQ4HDgWWbugLl3V1V5fbP5O0AtiT5oygQ8rDFgK3k+CPiOjMuMFv+wngckkrbN+7KUUkzQIOBBYDewwvtm57taTdx3nOXMpkcDNnztyU8hERMUIvZ/X8WNI1ktZIelzSVZJm9FpA0i7AVcDZZeqHntieb3vQ9uDAwECvT4uIiEn0EvwXA9cBr6EZqvlG2TcpSVNpQv9S21eX3Y9Lml7unw6s2dCmIyJi4/US/Lvbvtj22nK5BJj0EFySgAXACttfGHHXdcCp5fapwLUb2HNERGyCXn65O1SmYb6sbJ8E/LiH5x0MnALcL2lZ2XcOcC5whaTTgB8C792wliNiSzBr3g2d1lt57tGd1tuW9RL87wf+O3A+YOD/lH0Tsn0HoHHuPqzXBiMiYvPqZQWuHwLHdtBLRER0IHP1RERUJsEfEVGZBH9ERGV6Dn5JB0m6VdI/STq+zaYiIqI94365K+lf2X5sxK6P0HzJK5oze/6h5d4iIqIFE53V83eSlgKfs/0L4GngPwDrgJ6nXoiIiC3LuEM9to8HlgHXSzoFOJsm9HcCMtQTEbGVmnCM3/Y3gH8HTAOuBh6yfYHtoS6ai4iIzW+ipRePlXQHcCuwHDgROEHSZZL26arBiIjYvCYa4/9L4C3AjsCNtucAH5G0L/AZmg+CiIjYykwU/D+hCfcdGTF1su2HSehHRGy1JhrjP4Hmi9y1NGfzRETENmCypRe/1GEvERHRgUzZEBFRmdaCX9JXyjq9y0fs+5SkH0laVi5HtVU/IiLG1uYR/yXAkWPsP9/27HK5scX6ERExhtaC3/a3gCfbev2IiNg4/RjjP0PSfWUo6JXjPUjSXElLJC0ZGsoPhSMiNpeug/9CYB9gNrAa+Px4D7Q93/ag7cGBgYGu+ouI2OZ1Gvy2H7f9ou11wJeBOV3Wj4iIjoNf0vQRmyfQzAEUEREdmmjKhk0i6TLgEGA3SauATwKHSJoNGFgJnN5W/YiIGFtrwW/7pDF2L2irXkRE9Ca/3I2IqEyCPyKiMgn+iIjKJPgjIiqT4I+IqEyCPyKiMgn+iIjKJPgjIiqT4I+IqEyCPyKiMgn+iIjKJPgjIiqT4I+IqEyCPyKiMgn+iIjKtBb8ZTH1NZKWj9j3KkmLJD1crsddbD0iItrR5hH/JcCRo/bNA26xvS9wS9mOiIgOtRb8tr8FPDlq93HAwnJ7IXB8W/UjImJsXY/x72F7NUC53n28B0qaK2mJpCVDQ0OdNRgRsa3bYr/ctT3f9qDtwYGBgX63ExGxzeg6+B+XNB2gXK/puH5ERPW6Dv7rgFPL7VOBazuuHxFRvTZP57wM+Dawn6RVkk4DzgXeIelh4B1lOyIiOrRdWy9s+6Rx7jqsrZoRETG5LfbL3YiIaEeCPyKiMgn+iIjKJPgjIiqT4I+IqEyCPyKiMgn+iIjKJPgjIiqT4I+IqEyCPyKiMq1N2RDRtVnzbui03spzj+60XsTmkiP+iIjKJPgjIiqT4I+IqEyCPyKiMn35clfSSuBnwIvAWtuD/egjIqJG/Tyr5+22n+hj/YiIKmWoJyKiMv0KfgPflLRU0tw+9RARUaV+DfUcbPtRSbsDiyQ9aPtbIx9QPhDmAsycObMfPUZEbJP6csRv+9FyvQa4BpgzxmPm2x60PTgwMNB1ixER26zOg1/SzpJ2Hb4NHAEs77qPiIha9WOoZw/gGknD9b9m+6Y+9BERUaXOg9/2I8ABXdeNiIhGTueMiKhMgj8iojIJ/oiIyiT4IyIqkxW4ImKrk9XWNk2O+CMiKpPgj4ioTII/IqIyCf6IiMok+CMiKpPgj4ioTII/IqIyCf6IiMok+CMiKpNf7sZmlV9URmz5csQfEVGZvgS/pCMlPSTpu5Lm9aOHiIhadT7UI2kK8DfAO4BVwF2SrrP9na57iYjYUNvCcGY/xvjnAN8tSzAi6XLgOGCbC/5+/gPpsnbG2SO2LrLdbUHpPcCRtv+obJ8CvNn2GaMeNxeYWzb3Ax7qtFHYDXii45r9rl3je661do3vucbav257YPTOfhzxa4x963362J4PzG+/nbFJWmJ7sKbaNb7nWmvX+J5rrj1aP77cXQXsNWJ7BvBoH/qIiKhSP4L/LmBfSXtL2h44EbiuD31ERFSp86Ee22slnQHcDEwBvmL7ga776EHfhpn6WLvG91xr7Rrfc821X6LzL3cjIqK/8svdiIjKJPgjIiqT4B9F0lckrZG0vOO6e0m6TdIKSQ9IOqvD2jtIulPSvaX2p7uqPaKHKZLukXR9x3VXSrpf0jJJSzqsO03SlZIeLP+fv6WjuvuV9zp8+amks7uoXer/Sfk3tlzSZZJ26KjuWaXmA12837FyRNKrJC2S9HC5fmXbfYwnwb++S4Aj+1B3LfBR268HDgI+JOlfd1T7eeBQ2wcAs4EjJR3UUe1hZwErOq457O22Z3d8jvVfAzfZfh1wAB29d9sPlfc6G3gj8BxwTRe1Je0JfBgYtL0/zckdJ3ZQd3/gP9LMGnAAcIykfVsuewnr58g84Bbb+wK3lO2+SPCPYvtbwJN9qLva9t3l9s9ogmDPjmrb9jNlc2q5dPatv6QZwNHARV3V7CdJrwDeBiwAsP1L20/3oZXDgO/Z/kGHNbcDdpS0HbAT3fyG5/XAP9t+zvZa4B+BE9osOE6OHAcsLLcXAse32cNEEvxbIEmzgAOBxR3WnCJpGbAGWGS7s9rAF4E/A9Z1WHOYgW9KWlqmCenCbwBDwMVleOsiSTt3VHukE4HLuipm+0fAXwE/BFYDP7H9zQ5KLwfeJunVknYCjuKlPyLtyh62V0NzoAfs3ocegAT/FkfSLsBVwNm2f9pVXdsvlj//ZwBzyp/HrZN0DLDG9tIu6o3hYNtvAN5JM7z2tg5qbge8AbjQ9oHAs3T8Z3/58eSxwNc7rPlKmqPevYHXADtLOrnturZXAOcBi4CbgHtphlarleDfgkiaShP6l9q+uh89lCGH2+nue46DgWMlrQQuBw6V9NWOamP70XK9hmase04HZVcBq0b8VXUlzQdBl94J3G378Q5rHg583/aQ7ReAq4Hf6aKw7QW232D7bTRDMA93UXeUxyVNByjXa/rQA5Dg32JIEs2Y7wrbX+i49oCkaeX2jjT/gT7YRW3bn7A9w/YsmqGHW223fhQIIGlnSbsO3waOoBkWaJXtx4D/K2m/suswup+W/CQ6HOYpfggcJGmn8u/9MDr6UlvS7uV6JvAuun/v0ExNc2q5fSpwbR96ALLm7nokXQYcAuwmaRXwSdsLOih9MHAKcH8Zawc4x/aNHdSeDiwsi+S8DLjCdqenVfbJHsA1TQaxHfA12zd1VPtM4NIy5PII8Icd1aWMc78DOL2rmgC2F0u6EribZqjlHrqbxuAqSa8GXgA+ZPupNouNlSPAucAVkk6j+RB8b5s9TNhfpmyIiKhLhnoiIiqT4I+IqEyCPyKiMgn+iIjKJPgjIiqT4I++k2RJnx+x/aeSPrWZXvsSSe/ZHK81SZ33llk2b2u7VsSmSvDHluB54F2Sdut3IyOV3zX06jTgg7bf3lY/EZtLgj+2BGtpfsjzJ6PvGH3ELumZcn2IpH+UdIWkf5F0rqTfL+sK3C9pnxEvc7ik/10ed0x5/hRJn5N0l6T7JJ0+4nVvk/Q14P4x+jmpvP5ySeeVff8VeCvwd5I+N+rxL5P0t2Ue+Osl3Tj8ftSsBbBbuT0o6fZye+cyn/tdZRK348r+3yrvb1nped/y2BvUrKWwXNLvlce+sfzvs1TSzSOmCviwpO+U51++Ef9fxTYgv9yNLcXfAPdJ+uwGPOcAmil3n6T59etFtueoWcTmTGB4wY1ZwO8C+wC3SfpN4H00s0O+SdLLgX+SNDxT5Bxgf9vfH1lM0mtoJvt6I/AUzayex9v+c0mHAn9qe/RiLu8q9f8NzWyMK4CvTPK+/hPN1BXvL1Np3CnpfwEfAP7a9vAvfqfQzDT5qO2jS4+/VuZ8+hJwnO2h8mHwGeD9NJPB7W37+eFpOqI+OeKPLUKZifR/0CzU0au7yjoGzwPfA4aD+36asB12he11th+m+YB4Hc28PO8r02MsBl4NDC/Ocefo0C/eBNxeJhlbC1xKM6/+RN4KfL3Ufwzo5TuAI4B5pbfbgR2AmcC3gXMkfRz4dds/L+/1cEnnSfq3tn8C7AfsDywqr/GfaWZdBbiPZqqIk6l8hsqa5Yg/tiRfpJnH5eIR+9ZSDlDKxF7bj7jv+RG3143YXsdL/22PnpfEgIAzbd888g5Jh9BMkzwWTfoONuw5//+90YT7yOe82/ZDox6/QtJimkVrbpb0R7ZvlfRGmiP//1b+arkGeMD2WMs5Hk3zYXUs8F8k/Vb5EIuK5Ig/thi2nwSuoPmidNhKmqEVaOZyn7oRL/3eMta+D80iKA8BNwN/XIZFkPRaTb4YymLgdyXtVr74PYlmNaeJ3AG8u9Tfg2birmEr+dV7e/eI/TcDZ5YPOiQdWK5/A3jE9gU0Mz3+dhl+es72V2kWOXlDeX8DKuv4Sppavh94GbCX7dtoFr6ZBuwySf+xDcoRf2xpPg+cMWL7y8C1ku6kWad0vKPxiTxEE9B7AB+w/QtJF9EMB91dAnaISZbCs71a0idohmsE3Gh7sql1r6KZfng58C80Hx4/Kfd9Glgg6RxeutraX9D89XNf6W0lcAzwe8DJkl4AHgP+nGb46XOS1tHMPPnHtn9ZvkC+QNKv0fx3/sVS/6tln4Dz+7TkY/RZZueMaJmkXWw/o2Za4DtpVv16rN99Rb1yxB/RvuvLGTTbA3+R0I9+yxF/RERl8uVuRERlEvwREZVJ8EdEVCbBHxFRmQR/RERl/h8eBbWnN98bnwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(neg_entropy, inconsistent=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Report Summary\n",
    "\n",
    "Here's a table of the mean and maximum number of guesses for the seven approaches:\n",
    "\n",
    "|<br><u>2,845 words</u><br>Algorithm|Consistent<br><u>Only</u><br>Mean (Max)|Inconsistent<br><u>Allowed</u><br>Mean (Max)|\n",
    "|--|--|--|\n",
    "|random guesser|7.42 (17)|  |\n",
    "|minimize max|7.15 (18)|7.05 (10)|\n",
    "|minimize expectation|7.14 (17)|6.84 (10)|\n",
    "|minimize neg_entropy|7.09 (19)|6.82 (10)|\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Wordle\n",
    "\n",
    "[Wordle](https://www.powerlanguage.co.uk/wordle/) is a [suddenly-popular](https://www.nytimes.com/2022/01/03/technology/wordle-word-game-creator.html) variant of Jotto (with a little Mastermind thrown in) with these differences:\n",
    "- Words with repeated letters are allowed (e.g. `'aback'`).\n",
    "- Anagrams are allowed (e.g. `'arise'` and `'raise'`).\n",
    "- The reply to a guess consists of 5 pieces ([trits](https://en.wiktionary.org/wiki/trit#English)) of information, one for each position in the guess:\n",
    "  - *Green* if the guess letter is in the correct spot.\n",
    "  - *Yellow* if the guess letter is in the word but in the wrong spot.\n",
    "  - *Miss* if the letter is not in the word in any spot.\n",
    "- Wordle uses a larger list of 12,971 allowable guess words, but only 2,315 of them can be target words. (I think the idea is to follow [Postel's law](https://en.wikipedia.org/wiki/Robustness_principle) to avoid annoying a player: be conservative in the targets (so that a player is very likely to be familiar with the target word) and be liberal in accepting guess words.)\n",
    "  \n",
    "There is an ambiguity in the rules. Assume the guess is *etude* and the target is *poems*. A strict reading of the rules would say they both *e* positions should be *yellow*, because both instances of *e* are \"in the word but in the wrong spot.\" But it seems Wordle actually reports the first *e* as yellow and the second *e* as a miss."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "wordle_small = read_words('wordle-small.txt') #  2,315 target words\n",
    "wordle_big   = read_words('wordle-big.txt')   # 12,971 guess  words\n",
    "\n",
    "Green, Yellow, Miss = 'GY.' # A Wordle reply is 5 characters, each one of 'GY.'\n",
    "\n",
    "def wordle_reply_for(guess, target) -> str: \n",
    "    \"The five-character reply for this guess on this target in Wordle.\"\n",
    "    # We'll start by having each reply be either Green or Miss ...\n",
    "    reply = [Green if guess[i] == target[i] else Miss for i in range(5)]\n",
    "    # ... then we'll change the replies that should be yellow\n",
    "    counts = Counter(target[i] for i in range(5) if guess[i] != target[i])\n",
    "    for i in range(5):\n",
    "        if reply[i] == Miss and counts[guess[i]] > 0:\n",
    "            counts[guess[i]] -= 1\n",
    "            reply[i] = Yellow\n",
    "    return ''.join(reply)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The right thing to do now would be to refactor the code to allow for the injection of a different `reply_for` function, so that either game could be played at any time.\n",
    "\n",
    "However, I'm going to take a shortcut: I'm going to require the programmer to call `setup` with the name of the game they want, `'jotto'` or `'wordle'`. It will set global variables accordingly. I'll also require the programmer to use the right word list and target words."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "jotto_reply_for = reply_for"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "def setup(game: str) -> None:\n",
    "    \"Set global variables to play either 'jotto' or 'wordle'.\"\n",
    "    global reply_for, inconsistent_max\n",
    "    if game == 'jotto':\n",
    "        reply_for = jotto_reply_for\n",
    "        inconsistent_max = 400\n",
    "    elif game == 'wordle':\n",
    "        reply_for = wordle_reply_for\n",
    "        inconsistent_max = 125\n",
    "    else:\n",
    "        raise ValueError(f'unknown game: {game}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "setup('wordle')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that in Jotto, `reply_for` was symmetric; `reply_for(g, t) == reply_for(t, g)`. But that is not true for Wordle.  I made some tests for `wordle_reply_for` to give me some confidence I got it right:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert reply_for('treat', 'truss') == 'GG...'  and  reply_for('truss', 'treat') == 'GG...'\n",
    "assert reply_for('stars', 'traps') == '.YGYG'  and  reply_for('traps', 'stars') == 'YYG.G'\n",
    "assert reply_for('palls', 'splat') == 'YYG.Y'  and  reply_for('splat', 'palls') == 'YYGY.'\n",
    "assert reply_for('banal', 'apple') == '.Y..Y'  and  reply_for('apple', 'banal') == 'Y..Y.'\n",
    "assert reply_for('banal', 'mania') == '.GGY.'  and  reply_for('mania', 'banal') == '.GG.Y'\n",
    "assert reply_for('epees', 'geese') == 'Y.GYY'  and  reply_for('geese', 'epees') == '.YGYY'\n",
    "assert reply_for('wheee', 'peeve') == '..GYG'  and  reply_for('peeve', 'wheee') == '.YG.G'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can test the new `reply_for` on a partition of `words22`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "defaultdict(list,\n",
       "            {'.YYYY': ['their'],\n",
       "             '...Y.': ['about'],\n",
       "             'G....': ['would'],\n",
       "             '.Y.YG': ['throe'],\n",
       "             'YY...': ['sword'],\n",
       "             '.....': ['cloud', 'sound', 'fondu'],\n",
       "             'GGGGG': ['write'],\n",
       "             '.YYG.': ['rifts', 'girth'],\n",
       "             'GY.YY': ['water'],\n",
       "             '.Y.YY': ['after'],\n",
       "             '..GY.': ['think'],\n",
       "             '.Y..Y': ['resay', 'nuder'],\n",
       "             '....G': ['place', 'house'],\n",
       "             '.G.GG': ['grate'],\n",
       "             '...YY': ['ethos'],\n",
       "             '..YY.': ['might'],\n",
       "             'G.G.G': ['while']})"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "partition('write', words22)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That looks good. Notice that there are many more possible replies in Wordle than the 6 possible replies in Jotto, so the target words are partitioned into smaller branches. It should take fewer guesses to solve a Wordle than a Jotto. How many possible replies are there? There are 3 responses at each of five positions, and  3<sup>5</sup> = 243, but five of those replies are impossible: you can't have four Greens and one Yellow, because if four letters of the guess are in the right place then the fifth must be either in the right place or a miss. \n",
    "\n",
    "# Sample Wordle Games\n",
    "\n",
    "Let's see what some Wordle games look like, using a random guesser:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"pluck\" Reply: .Y...; Consistent targets: 269\n",
      "Guess 2: \"false\" Reply: ..G.Y; Consistent targets: 9\n",
      "Guess 3: \"below\" Reply: GGGGG; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(random_guesser, wordlist=wordle_small)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"caddy\" Reply: .....; Consistent targets: 729\n",
      "Guess 2: \"rupee\" Reply: Y....; Consistent targets: 62\n",
      "Guess 3: \"snort\" Reply: G.GGY; Consistent targets: 2\n",
      "Guess 4: \"stork\" Reply: GGGG.; Consistent targets: 1\n",
      "Guess 5: \"storm\" Reply: GGGGG; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(random_guesser, wordlist=wordle_small)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"wiser\" Reply: .G...; Consistent targets: 73\n",
      "Guess 2: \"ninth\" Reply: .GG..; Consistent targets: 9\n",
      "Guess 3: \"final\" Reply: .GG.G; Consistent targets: 1\n",
      "Guess 4: \"vinyl\" Reply: GGGGG; Consistent targets: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "play(random_guesser, wordlist=wordle_small)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Reports on Wordle Guessers\n",
    "\n",
    "Wordle has about the same number of target words as Jotto, but many more guess words, and the `wordle_reply_for` computation is more complex, so computations take longer (more so for the inconsistent guessers). Here are reports on the seven strategies:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "median: 4 guesses, mean: 4.10 ± 1.04, worst: 8, scores: 2,315\n",
      "cumulative: ≤3:28%, ≤4:69%, ≤5:92%, ≤6:98%, ≤7:99.4%, ≤8:100%, ≤9:100%, ≤10:100%\n",
      "CPU times: user 30.1 s, sys: 29.3 ms, total: 30.1 s\n",
      "Wall time: 30.2 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time report(play(random_guesser, target, wordle_small, verbose=False) for target in wordle_small)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the max of partition sizes over 2,315 targets in a 12,971 word list,\n",
      "not including inconsistent words.\n",
      "first guess: \"arise\"\n",
      "median: 4 guesses, mean: 3.68 ± 0.86, worst: 8, scores: 2,315\n",
      "cumulative: ≤3:43%, ≤4:87%, ≤5:97%, ≤6:99.4%, ≤7:99.9%, ≤8:100%, ≤9:100%, ≤10:100%\n",
      "CPU times: user 29 s, sys: 36.4 ms, total: 29 s\n",
      "Wall time: 29 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(max, wordle_small, wordle_big, inconsistent=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the expectation of partition sizes over 2,315 targets in a 12,971 word list,\n",
      "not including inconsistent words.\n",
      "first guess: \"raise\"\n",
      "median: 4 guesses, mean: 3.62 ± 0.86, worst: 8, scores: 2,315\n",
      "cumulative: ≤3:47%, ≤4:88%, ≤5:98%, ≤6:99.4%, ≤7:99.9%, ≤8:100%, ≤9:100%, ≤10:100%\n",
      "CPU times: user 29.2 s, sys: 25.8 ms, total: 29.2 s\n",
      "Wall time: 29.2 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(expectation, wordle_small, wordle_big, inconsistent=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the neg_entropy of partition sizes over 2,315 targets in a 12,971 word list,\n",
      "not including inconsistent words.\n",
      "first guess: \"raise\"\n",
      "median: 4 guesses, mean: 3.60 ± 0.85, worst: 8, scores: 2,315\n",
      "cumulative: ≤3:49%, ≤4:89%, ≤5:97%, ≤6:99.5%, ≤7:99.9%, ≤8:100%, ≤9:100%, ≤10:100%\n",
      "CPU times: user 29.1 s, sys: 25.4 ms, total: 29.2 s\n",
      "Wall time: 29.2 s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(neg_entropy, wordle_small, wordle_big, inconsistent=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **inconsistent guessers** will each take about 4 minutes to compute:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the max of partition sizes over 2,315 targets in a 12,971 word list,\n",
      "including inconsistent words.\n",
      "first guess: \"arise\"\n",
      "median: 4 guesses, mean: 3.62 ± 0.64, worst: 6, scores: 2,315\n",
      "cumulative: ≤3:42%, ≤4:94%, ≤5:99.7%, ≤6:100%, ≤7:100%, ≤8:100%, ≤9:100%, ≤10:100%\n",
      "CPU times: user 4min 3s, sys: 193 ms, total: 4min 3s\n",
      "Wall time: 4min 7s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(max, wordle_small, wordle_big, inconsistent=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the expectation of partition sizes over 2,315 targets in a 12,971 word list,\n",
      "including inconsistent words.\n",
      "first guess: \"raise\"\n",
      "median: 4 guesses, mean: 3.52 ± 0.62, worst: 6, scores: 2,315\n",
      "cumulative: ≤3:50%, ≤4:96%, ≤5:99.8%, ≤6:100%, ≤7:100%, ≤8:100%, ≤9:100%, ≤10:100%\n",
      "CPU times: user 4min 47s, sys: 144 ms, total: 4min 47s\n",
      "Wall time: 4min 58s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(expectation, wordle_small, wordle_big, inconsistent=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "minimizing the neg_entropy of partition sizes over 2,315 targets in a 12,971 word list,\n",
      "including inconsistent words.\n",
      "first guess: \"raise\"\n",
      "median: 3 guesses, mean: 3.50 ± 0.62, worst: 6, scores: 2,315\n",
      "cumulative: ≤3:52%, ≤4:96%, ≤5:99.7%, ≤6:100%, ≤7:100%, ≤8:100%, ≤9:100%, ≤10:100%\n",
      "CPU times: user 4min 26s, sys: 147 ms, total: 4min 26s\n",
      "Wall time: 4min 34s\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%time t = report_minimizing_tree(neg_entropy, wordle_small, wordle_big, inconsistent=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Mission accomplished!** All three metrics solve every target word in 6 guesses or less. \n",
    "\n",
    "# Jotto and Wordle Evaluation Summary\n",
    "\n",
    "Here is a summary of the reports on both games:\n",
    "\n",
    "|<br><br><br>Algorithm|JOTTO<br>Consistent<br><u>Only</u><br>Mean (Max)|JOTTO<br>Inconsistent<br><u>Allowed</u><br>Mean (Max)|WORDLE<br>Consistent<br><u>Only</u><br>Mean (Max)|WORDLE<br>Inconsistent<br><u>Allowed</u><br>Mean (Max)||\n",
    "|--|--|--|--|--|--|\n",
    "|random guesser|7.34 (18)|  |4.10 (8) |   |\n",
    "|minimize max|7.15 (18)|7.05 (10)| 3.68 (8) | 3.62 (6) | \n",
    "|minimize expectation|7.14 (17)|6.84 (10)| 3.62 (8) | 3.52 (6) | \n",
    "|minimize neg_entropy|7.09 (19)|6.82 (10)| 3.60 (8) |  3.50 (6) |\n",
    "\n",
    "\n",
    "# Sample Wordle Games with Minimizing Guesser\n",
    "\n",
    "Here are some sample games with the negative-entropy minimizing, inconsistent-guessing guesser:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Guess 1: \"raise\" Reply: ...YY; Consistent targets: 797\n",
      "Guess 2: \"spelt\" Reply: G.GG.; Consistent targets: 11\n",
      "Guess 3: \"fehme\" Reply: .Y...; Consistent targets: 3\n",
      "Guess 4: \"swell\" Reply: GGGGG; Consistent targets: 1\n",
      "\n",
      "Guess 1: \"raise\" Reply: YY...; Consistent targets: 297\n",
      "Guess 2: \"tronc\" Reply: .G..Y; Consistent targets: 12\n",
      "Guess 3: \"calmy\" Reply: GY..G; Consistent targets: 2\n",
      "Guess 4: \"crazy\" Reply: GGGGG; Consistent targets: 1\n",
      "\n",
      "Guess 1: \"raise\" Reply: YY...; Consistent targets: 297\n",
      "Guess 2: \"tronc\" Reply: .GY..; Consistent targets: 8\n",
      "Guess 3: \"abram\" Reply: G.G..; Consistent targets: 2\n",
      "Guess 4: \"arrow\" Reply: GGGGG; Consistent targets: 1\n",
      "\n",
      "Guess 1: \"raise\" Reply: Y.G..; Consistent targets: 75\n",
      "Guess 2: \"crypt\" Reply: .G.Y.; Consistent targets: 7\n",
      "Guess 3: \"primo\" Reply: GGGGG; Consistent targets: 1\n",
      "\n",
      "Guess 1: \"raise\" Reply: ..YY.; Consistent targets: 343\n",
      "Guess 2: \"shout\" Reply: Y.Y..; Consistent targets: 46\n",
      "Guess 3: \"bison\" Reply: .GGY.; Consistent targets: 6\n",
      "Guess 4: \"disco\" Reply: GGGGG; Consistent targets: 1\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for target in random.sample(wordle_small, 5):\n",
    "    play(TreeGuesser(t), target, wordle_big)\n",
    "    print()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Best and Worst First Guess Words\n",
    "\n",
    "Here's a function to create a table of the best and worst first guesses in a game (that is, the highest and lowest scoring words on the partition counts), according to each of the three metrics:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "def first_guesses(targets, wordlist) -> pd.DataFrame: \n",
    "    \"\"\"A data frame of words and scores on the 3 metrics, sorted best to worst.\"\"\"\n",
    "    metrics = (max, expectation, neg_entropy)\n",
    "    data = [sorted((metric(partition_counts(g, targets)), g) for g in wordlist)\n",
    "            for metric in metrics]\n",
    "    def reformat(row):\n",
    "        (val1, word1), (val2, word2), (val3, word3) = row\n",
    "        return [word1, val1, word2, round(val2, 2), word3, round(val3, 3)]\n",
    "    return pd.DataFrame(map(reformat, zip(*data)), \n",
    "                        columns='max_word max exp_word exp ent_word ent'.split())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The best and worst first guesses for **Jotto**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 13.9 s, sys: 7.46 ms, total: 13.9 s\n",
      "Wall time: 13.9 s\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>max_word</th>\n",
       "      <th>max</th>\n",
       "      <th>exp_word</th>\n",
       "      <th>exp</th>\n",
       "      <th>ent_word</th>\n",
       "      <th>ent</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>wader</td>\n",
       "      <td>1012</td>\n",
       "      <td>raved</td>\n",
       "      <td>812.84</td>\n",
       "      <td>debar</td>\n",
       "      <td>-1.949</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>cadre</td>\n",
       "      <td>1026</td>\n",
       "      <td>debar</td>\n",
       "      <td>818.32</td>\n",
       "      <td>alder</td>\n",
       "      <td>-1.946</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>armed</td>\n",
       "      <td>1028</td>\n",
       "      <td>roved</td>\n",
       "      <td>826.51</td>\n",
       "      <td>raved</td>\n",
       "      <td>-1.944</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>diner</td>\n",
       "      <td>1029</td>\n",
       "      <td>orbed</td>\n",
       "      <td>826.71</td>\n",
       "      <td>dater</td>\n",
       "      <td>-1.943</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>coder</td>\n",
       "      <td>1030</td>\n",
       "      <td>wader</td>\n",
       "      <td>827.04</td>\n",
       "      <td>cadre</td>\n",
       "      <td>-1.943</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2840</th>\n",
       "      <td>coqui</td>\n",
       "      <td>1535</td>\n",
       "      <td>okapi</td>\n",
       "      <td>1105.28</td>\n",
       "      <td>jumpy</td>\n",
       "      <td>-1.575</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2841</th>\n",
       "      <td>quota</td>\n",
       "      <td>1548</td>\n",
       "      <td>azoic</td>\n",
       "      <td>1120.19</td>\n",
       "      <td>juicy</td>\n",
       "      <td>-1.566</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2842</th>\n",
       "      <td>azoic</td>\n",
       "      <td>1555</td>\n",
       "      <td>axiom</td>\n",
       "      <td>1157.49</td>\n",
       "      <td>axiom</td>\n",
       "      <td>-1.563</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2843</th>\n",
       "      <td>axiom</td>\n",
       "      <td>1615</td>\n",
       "      <td>audio</td>\n",
       "      <td>1184.28</td>\n",
       "      <td>audio</td>\n",
       "      <td>-1.494</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2844</th>\n",
       "      <td>ouija</td>\n",
       "      <td>1848</td>\n",
       "      <td>ouija</td>\n",
       "      <td>1413.00</td>\n",
       "      <td>ouija</td>\n",
       "      <td>-1.292</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2845 rows × 6 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     max_word   max exp_word      exp ent_word    ent\n",
       "0       wader  1012    raved   812.84    debar -1.949\n",
       "1       cadre  1026    debar   818.32    alder -1.946\n",
       "2       armed  1028    roved   826.51    raved -1.944\n",
       "3       diner  1029    orbed   826.71    dater -1.943\n",
       "4       coder  1030    wader   827.04    cadre -1.943\n",
       "...       ...   ...      ...      ...      ...    ...\n",
       "2840    coqui  1535    okapi  1105.28    jumpy -1.575\n",
       "2841    quota  1548    azoic  1120.19    juicy -1.566\n",
       "2842    azoic  1555    axiom  1157.49    axiom -1.563\n",
       "2843    axiom  1615    audio  1184.28    audio -1.494\n",
       "2844    ouija  1848    ouija  1413.00    ouija -1.292\n",
       "\n",
       "[2845 rows x 6 columns]"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "setup('jotto')\n",
    "%time df = first_guesses(wordlist, wordlist)\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The top guesses  favor the letters \"a\", \"d\", \"e\", and \"r\". \n",
    "\n",
    "The word \"ouija\" is a uniquely terrible guess; mostly what it does is confirm that a majority of the words have exactly one of the vowels \"aiou\". The output above only shows the top 5 guesses; here are the top 20:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>max_word</th>\n",
       "      <th>max</th>\n",
       "      <th>exp_word</th>\n",
       "      <th>exp</th>\n",
       "      <th>ent_word</th>\n",
       "      <th>ent</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>wader</td>\n",
       "      <td>1012</td>\n",
       "      <td>raved</td>\n",
       "      <td>812.84</td>\n",
       "      <td>debar</td>\n",
       "      <td>-1.949</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>cadre</td>\n",
       "      <td>1026</td>\n",
       "      <td>debar</td>\n",
       "      <td>818.32</td>\n",
       "      <td>alder</td>\n",
       "      <td>-1.946</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>armed</td>\n",
       "      <td>1028</td>\n",
       "      <td>roved</td>\n",
       "      <td>826.51</td>\n",
       "      <td>raved</td>\n",
       "      <td>-1.944</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>diner</td>\n",
       "      <td>1029</td>\n",
       "      <td>orbed</td>\n",
       "      <td>826.71</td>\n",
       "      <td>dater</td>\n",
       "      <td>-1.943</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>coder</td>\n",
       "      <td>1030</td>\n",
       "      <td>wader</td>\n",
       "      <td>827.04</td>\n",
       "      <td>cadre</td>\n",
       "      <td>-1.943</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>padre</td>\n",
       "      <td>1035</td>\n",
       "      <td>armed</td>\n",
       "      <td>827.28</td>\n",
       "      <td>armed</td>\n",
       "      <td>-1.939</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>raved</td>\n",
       "      <td>1038</td>\n",
       "      <td>fader</td>\n",
       "      <td>828.28</td>\n",
       "      <td>garde</td>\n",
       "      <td>-1.938</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>rayed</td>\n",
       "      <td>1038</td>\n",
       "      <td>dater</td>\n",
       "      <td>829.41</td>\n",
       "      <td>wader</td>\n",
       "      <td>-1.938</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>delta</td>\n",
       "      <td>1039</td>\n",
       "      <td>alder</td>\n",
       "      <td>829.96</td>\n",
       "      <td>lased</td>\n",
       "      <td>-1.935</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>drone</td>\n",
       "      <td>1041</td>\n",
       "      <td>cadre</td>\n",
       "      <td>829.98</td>\n",
       "      <td>padre</td>\n",
       "      <td>-1.934</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>eland</td>\n",
       "      <td>1043</td>\n",
       "      <td>garde</td>\n",
       "      <td>830.47</td>\n",
       "      <td>fader</td>\n",
       "      <td>-1.934</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>garde</td>\n",
       "      <td>1043</td>\n",
       "      <td>padre</td>\n",
       "      <td>831.76</td>\n",
       "      <td>dears</td>\n",
       "      <td>-1.933</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>heard</td>\n",
       "      <td>1044</td>\n",
       "      <td>deign</td>\n",
       "      <td>832.29</td>\n",
       "      <td>drone</td>\n",
       "      <td>-1.931</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>tired</td>\n",
       "      <td>1044</td>\n",
       "      <td>gored</td>\n",
       "      <td>833.68</td>\n",
       "      <td>diner</td>\n",
       "      <td>-1.931</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>debar</td>\n",
       "      <td>1046</td>\n",
       "      <td>laved</td>\n",
       "      <td>834.20</td>\n",
       "      <td>rayed</td>\n",
       "      <td>-1.931</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>fader</td>\n",
       "      <td>1048</td>\n",
       "      <td>rayed</td>\n",
       "      <td>836.51</td>\n",
       "      <td>tired</td>\n",
       "      <td>-1.929</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>ailed</td>\n",
       "      <td>1050</td>\n",
       "      <td>drone</td>\n",
       "      <td>836.74</td>\n",
       "      <td>orbed</td>\n",
       "      <td>-1.927</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>orbed</td>\n",
       "      <td>1052</td>\n",
       "      <td>oared</td>\n",
       "      <td>836.91</td>\n",
       "      <td>roved</td>\n",
       "      <td>-1.925</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>blear</td>\n",
       "      <td>1054</td>\n",
       "      <td>dower</td>\n",
       "      <td>837.57</td>\n",
       "      <td>coder</td>\n",
       "      <td>-1.924</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>raths</td>\n",
       "      <td>1054</td>\n",
       "      <td>coder</td>\n",
       "      <td>838.35</td>\n",
       "      <td>abled</td>\n",
       "      <td>-1.924</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   max_word   max exp_word     exp ent_word    ent\n",
       "0     wader  1012    raved  812.84    debar -1.949\n",
       "1     cadre  1026    debar  818.32    alder -1.946\n",
       "2     armed  1028    roved  826.51    raved -1.944\n",
       "3     diner  1029    orbed  826.71    dater -1.943\n",
       "4     coder  1030    wader  827.04    cadre -1.943\n",
       "5     padre  1035    armed  827.28    armed -1.939\n",
       "6     raved  1038    fader  828.28    garde -1.938\n",
       "7     rayed  1038    dater  829.41    wader -1.938\n",
       "8     delta  1039    alder  829.96    lased -1.935\n",
       "9     drone  1041    cadre  829.98    padre -1.934\n",
       "10    eland  1043    garde  830.47    fader -1.934\n",
       "11    garde  1043    padre  831.76    dears -1.933\n",
       "12    heard  1044    deign  832.29    drone -1.931\n",
       "13    tired  1044    gored  833.68    diner -1.931\n",
       "14    debar  1046    laved  834.20    rayed -1.931\n",
       "15    fader  1048    rayed  836.51    tired -1.929\n",
       "16    ailed  1050    drone  836.74    orbed -1.927\n",
       "17    orbed  1052    oared  836.91    roved -1.925\n",
       "18    blear  1054    dower  837.57    coder -1.924\n",
       "19    raths  1054    coder  838.35    abled -1.924"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[:20]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The best and worst first guesses for **Wordle**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 9min 17s, sys: 291 ms, total: 9min 17s\n",
      "Wall time: 9min 36s\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>max_word</th>\n",
       "      <th>max</th>\n",
       "      <th>exp_word</th>\n",
       "      <th>exp</th>\n",
       "      <th>ent_word</th>\n",
       "      <th>ent</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>aesir</td>\n",
       "      <td>168</td>\n",
       "      <td>roate</td>\n",
       "      <td>60.42</td>\n",
       "      <td>soare</td>\n",
       "      <td>-5.886</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>arise</td>\n",
       "      <td>168</td>\n",
       "      <td>raise</td>\n",
       "      <td>61.00</td>\n",
       "      <td>roate</td>\n",
       "      <td>-5.883</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>raise</td>\n",
       "      <td>168</td>\n",
       "      <td>raile</td>\n",
       "      <td>61.33</td>\n",
       "      <td>raise</td>\n",
       "      <td>-5.878</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>reais</td>\n",
       "      <td>168</td>\n",
       "      <td>soare</td>\n",
       "      <td>62.30</td>\n",
       "      <td>raile</td>\n",
       "      <td>-5.866</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>serai</td>\n",
       "      <td>168</td>\n",
       "      <td>arise</td>\n",
       "      <td>63.73</td>\n",
       "      <td>reast</td>\n",
       "      <td>-5.865</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12966</th>\n",
       "      <td>susus</td>\n",
       "      <td>1369</td>\n",
       "      <td>gyppy</td>\n",
       "      <td>885.90</td>\n",
       "      <td>yukky</td>\n",
       "      <td>-2.205</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12967</th>\n",
       "      <td>fuffy</td>\n",
       "      <td>1374</td>\n",
       "      <td>jugum</td>\n",
       "      <td>900.61</td>\n",
       "      <td>xylyl</td>\n",
       "      <td>-2.192</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12968</th>\n",
       "      <td>gyppy</td>\n",
       "      <td>1380</td>\n",
       "      <td>jujus</td>\n",
       "      <td>903.31</td>\n",
       "      <td>immix</td>\n",
       "      <td>-2.053</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12969</th>\n",
       "      <td>jugum</td>\n",
       "      <td>1410</td>\n",
       "      <td>qajaq</td>\n",
       "      <td>925.11</td>\n",
       "      <td>jujus</td>\n",
       "      <td>-2.038</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12970</th>\n",
       "      <td>immix</td>\n",
       "      <td>1429</td>\n",
       "      <td>immix</td>\n",
       "      <td>967.40</td>\n",
       "      <td>qajaq</td>\n",
       "      <td>-1.892</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>12971 rows × 6 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      max_word   max exp_word     exp ent_word    ent\n",
       "0        aesir   168    roate   60.42    soare -5.886\n",
       "1        arise   168    raise   61.00    roate -5.883\n",
       "2        raise   168    raile   61.33    raise -5.878\n",
       "3        reais   168    soare   62.30    raile -5.866\n",
       "4        serai   168    arise   63.73    reast -5.865\n",
       "...        ...   ...      ...     ...      ...    ...\n",
       "12966    susus  1369    gyppy  885.90    yukky -2.205\n",
       "12967    fuffy  1374    jugum  900.61    xylyl -2.192\n",
       "12968    gyppy  1380    jujus  903.31    immix -2.053\n",
       "12969    jugum  1410    qajaq  925.11    jujus -2.038\n",
       "12970    immix  1429    immix  967.40    qajaq -1.892\n",
       "\n",
       "[12971 rows x 6 columns]"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "setup('wordle')\n",
    "%time df2 = first_guesses(wordle_small, wordle_big)\n",
    "df2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Again, the best words use popular letters. One difference is that in Jotto, the best guesses have two vowels, in Wordle three. The worst words have repeated unpopular letters, like \"qajaq\" and \"yukky\". Here are the top 20 guesses:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>max_word</th>\n",
       "      <th>max</th>\n",
       "      <th>exp_word</th>\n",
       "      <th>exp</th>\n",
       "      <th>ent_word</th>\n",
       "      <th>ent</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>aesir</td>\n",
       "      <td>168</td>\n",
       "      <td>roate</td>\n",
       "      <td>60.42</td>\n",
       "      <td>soare</td>\n",
       "      <td>-5.886</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>arise</td>\n",
       "      <td>168</td>\n",
       "      <td>raise</td>\n",
       "      <td>61.00</td>\n",
       "      <td>roate</td>\n",
       "      <td>-5.883</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>raise</td>\n",
       "      <td>168</td>\n",
       "      <td>raile</td>\n",
       "      <td>61.33</td>\n",
       "      <td>raise</td>\n",
       "      <td>-5.878</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>reais</td>\n",
       "      <td>168</td>\n",
       "      <td>soare</td>\n",
       "      <td>62.30</td>\n",
       "      <td>raile</td>\n",
       "      <td>-5.866</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>serai</td>\n",
       "      <td>168</td>\n",
       "      <td>arise</td>\n",
       "      <td>63.73</td>\n",
       "      <td>reast</td>\n",
       "      <td>-5.865</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>aiery</td>\n",
       "      <td>171</td>\n",
       "      <td>irate</td>\n",
       "      <td>63.78</td>\n",
       "      <td>slate</td>\n",
       "      <td>-5.856</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>ayrie</td>\n",
       "      <td>171</td>\n",
       "      <td>orate</td>\n",
       "      <td>63.89</td>\n",
       "      <td>crate</td>\n",
       "      <td>-5.835</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>ariel</td>\n",
       "      <td>173</td>\n",
       "      <td>ariel</td>\n",
       "      <td>65.29</td>\n",
       "      <td>salet</td>\n",
       "      <td>-5.835</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>raile</td>\n",
       "      <td>173</td>\n",
       "      <td>arose</td>\n",
       "      <td>66.02</td>\n",
       "      <td>irate</td>\n",
       "      <td>-5.831</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>aloes</td>\n",
       "      <td>174</td>\n",
       "      <td>raine</td>\n",
       "      <td>67.06</td>\n",
       "      <td>trace</td>\n",
       "      <td>-5.831</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>realo</td>\n",
       "      <td>176</td>\n",
       "      <td>artel</td>\n",
       "      <td>67.50</td>\n",
       "      <td>arise</td>\n",
       "      <td>-5.821</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>stoae</td>\n",
       "      <td>177</td>\n",
       "      <td>taler</td>\n",
       "      <td>67.74</td>\n",
       "      <td>orate</td>\n",
       "      <td>-5.817</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>alone</td>\n",
       "      <td>182</td>\n",
       "      <td>ratel</td>\n",
       "      <td>69.84</td>\n",
       "      <td>stare</td>\n",
       "      <td>-5.807</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>anole</td>\n",
       "      <td>182</td>\n",
       "      <td>aesir</td>\n",
       "      <td>69.88</td>\n",
       "      <td>carte</td>\n",
       "      <td>-5.795</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>aeros</td>\n",
       "      <td>183</td>\n",
       "      <td>arles</td>\n",
       "      <td>69.89</td>\n",
       "      <td>raine</td>\n",
       "      <td>-5.787</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>arose</td>\n",
       "      <td>183</td>\n",
       "      <td>realo</td>\n",
       "      <td>69.95</td>\n",
       "      <td>caret</td>\n",
       "      <td>-5.777</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>soare</td>\n",
       "      <td>183</td>\n",
       "      <td>alter</td>\n",
       "      <td>69.99</td>\n",
       "      <td>ariel</td>\n",
       "      <td>-5.775</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>oiler</td>\n",
       "      <td>186</td>\n",
       "      <td>saner</td>\n",
       "      <td>70.13</td>\n",
       "      <td>taler</td>\n",
       "      <td>-5.771</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>oriel</td>\n",
       "      <td>186</td>\n",
       "      <td>later</td>\n",
       "      <td>70.22</td>\n",
       "      <td>carle</td>\n",
       "      <td>-5.770</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>reoil</td>\n",
       "      <td>186</td>\n",
       "      <td>snare</td>\n",
       "      <td>71.10</td>\n",
       "      <td>slane</td>\n",
       "      <td>-5.770</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   max_word  max exp_word    exp ent_word    ent\n",
       "0     aesir  168    roate  60.42    soare -5.886\n",
       "1     arise  168    raise  61.00    roate -5.883\n",
       "2     raise  168    raile  61.33    raise -5.878\n",
       "3     reais  168    soare  62.30    raile -5.866\n",
       "4     serai  168    arise  63.73    reast -5.865\n",
       "5     aiery  171    irate  63.78    slate -5.856\n",
       "6     ayrie  171    orate  63.89    crate -5.835\n",
       "7     ariel  173    ariel  65.29    salet -5.835\n",
       "8     raile  173    arose  66.02    irate -5.831\n",
       "9     aloes  174    raine  67.06    trace -5.831\n",
       "10    realo  176    artel  67.50    arise -5.821\n",
       "11    stoae  177    taler  67.74    orate -5.817\n",
       "12    alone  182    ratel  69.84    stare -5.807\n",
       "13    anole  182    aesir  69.88    carte -5.795\n",
       "14    aeros  183    arles  69.89    raine -5.787\n",
       "15    arose  183    realo  69.95    caret -5.777\n",
       "16    soare  183    alter  69.99    ariel -5.775\n",
       "17    oiler  186    saner  70.13    taler -5.771\n",
       "18    oriel  186    later  70.22    carle -5.770\n",
       "19    reoil  186    snare  71.10    slane -5.770"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df2[:20]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Next Steps\n",
    "\n",
    "There are many directions you could take this if you are interested:\n",
    "- **Other games:**\n",
    "  - Consider a Jotto game variant where each reply consists of two numbers: the number of letters in common with the target, and the number of letters that are in the exact correct position (as in Mastermind).\n",
    "  - Implement [Mastermind](https://en.wikipedia.org/wiki/Mastermind_%28board_game%29). The default version has 6 colors and 4 pegs. Can you go beyond that?\n",
    "  - Research what other computer scientists have done with [Jotto](https://arxiv.org/abs/1107.3342) or [Mastermind](http://serkangur.freeservers.com/).\n",
    "  - Refactor the code so it can smoothly handle multiple different games.\n",
    "- **Better strategy**:\n",
    "  - Our `minimizing_tree` function is **greedy** in that it guesses the word that minimizes some metric of the current situation without looking ahead to future branches in the tree. Can you get better performance by doing some **look-ahead**? Perhaps with a beam search?\n",
    "  - As an alternative to look-ahead, can you improve a tree by editing it? Given a tree, look for interior nodes that end up with a worse-than-expected average score, and see if the node can be replaced with something better (covering the same target words). Correcting a few bad nodes might be faster than carefully searching for good nodes in the first place.\n",
    "  - The three metrics (max, expectation, and negative entropy) are all designed as proxies to what we really want to minimize: the average number of guesses. Can we estimate that directly? For example, we know a branch of size 1 will always take 1 guess; of size 2 an average of 3/2 guesses; and of size 3 an average of 5/3 guesses if one of the words partitions the other two, otherwise an average of 2. Can we learn a function that takes a set of words as input and estimates the average number of guesses for the set? Would a deep neural net be a good way to learn this function?\n",
    "  - Is it feasible to do a complete search and find the guaranteed optimal strategy? What optimizations to the code would be necessary? How long would the search take?\n",
    "- **Chooser strategy**:\n",
    "  - Analyze the game where the chooser is not random, but rather is an adversary to the guesser–the chooser tries to choose a word that will maximize the guesser's score. What's a good strategy for the chooser? Is there a strategy equilibrium?\n",
    "  - Refactor `play` to accomodate three roles:\n",
    "    - A chooser, who decides what the target word is.\n",
    "    - A guesser, who guesses the target word.\n",
    "    - A replier, who says what the reply to the guess is."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
